package com.sz.common.core.system.service.impl;

import com.google.common.eventbus.EventBus;
import com.sz.common.base.constants.TemplateConstants;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.DaoSupport;
import com.sz.common.base.dao.Pagination;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.service.role.MembershipType;
import com.sz.common.core.service.role.RoleMembership;
import com.sz.common.core.constants.SysErrorCodes;
import com.sz.common.core.constants.ModuleNames;
import com.sz.common.core.system.entity.*;
import com.sz.common.core.system.service.SysFileService;
import com.sz.common.core.system.service.SysMailService;
import com.sz.common.core.system.dto.OrgUserDto;
import com.sz.common.core.system.dto.SimpleUserDto;
import com.sz.common.core.system.dto.UserChangePasswordDto;
import com.sz.common.core.system.dto.UserDto;
import com.sz.common.core.system.service.OrgService;
import com.sz.common.core.system.service.UserService;
import com.sz.common.base.utils.*;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Function: UserServiceImpl <br>
 * Author: wentao.chang <br>
 * Date: 2016-10-18 09:45:00
 */
@Service
public class UserServiceImpl extends AbstractService implements UserService {

    @Resource(name = "daoSupport")
    private DaoSupport dao;

    @Autowired
    private SysMailService mailService;

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private OrgService orgService;

    @Autowired
    EventBus eventBus;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int saveUser(UserDto userDto) throws ParseException {
        checkDataValid(userDto);
        User user = new User();
        BeanUtils.copyProperties(userDto, user);
        user.setUserName(user.getCode());
        UserDetail userDetail = new UserDetail();
        BeanUtils.copyProperties(userDto, userDetail);
        // 检查数据不能重复
        checkUserExist(user);

        String credentialSalt = CredentialUtils.generateSalt();
        user.setCredentialSalt(credentialSalt);
        String randomPassword = CredentialUtils.randomPassword();
        user.setPassword(new Md5Hash(randomPassword, credentialSalt).toString().toUpperCase());
        user.setIsDeleted(false);
        user.setIsLocked(false);
        user.setIsSystem(false);
        dao.save("UserMapper.insert", user);

        userDetail.setUserId(user.getId());
        if (StringUtils.hasLength(userDto.getBirthday())) {
            userDetail.setBirthday(DateUtils.convertToDate(userDto.getBirthday(), DateUtils.FORMAT_SIMPLE));
        } else {
            userDetail.setBirthday(DateUtils.convertToDate("1970-01-01", DateUtils.FORMAT_SIMPLE));
        }
        dao.save("UserDetailMapper.insert", userDetail);
        // 新增到用户组织表中
        UserOrg uo = new UserOrg();
        uo.setOrgId(userDto.getOrgId());
        uo.setUserId(user.getId());
        dao.save("UserOrgMapper.insert", uo);

        //设置头像为非临时等信息
        SysFile sysFile = sysFileService.getFileContent(userDto.getAvatarId());
        if (sysFile != null && sysFile.getIsTempFile()) {
            sysFileService.updateFileInfo(sysFile.getFileId(), "sys_user", sysFile.getFileName(), sysFile.getContentType(),
                    "用户" + user.getId() + "头像", false, 1);
        }
        Map<String, Object> emailBodyMap = new HashMap<>();
        emailBodyMap.put("username", user.getCode());
        emailBodyMap.put("password", randomPassword);
        String emailBody = JsonUtils.toJSONString(emailBodyMap);
        // 发邮件
        mailService.createMail("sys.logistics.master@hna.com", new String[]{user.getEmail()}, "运营平台账号初始密码通知",
                emailBody, TemplateConstants.INIT_PASSWORD);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_USER", userDto);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.ADD, "新建用户", dataBackup);
        return user.getId();
    }


    /**
     * 按过滤条件过滤用户信息列表
     *
     * @param isIncludeSubOrg 是否包含子组织的用户
     * @see UserService#findByFilterListPage(int, int
     *, java.lang.String, boolean, int, int)
     */
    @Override
    public ResultDto findByFilterListPage(int orgid, int locked, String q, boolean isIncludeSubOrg, int pageindex, int pageSize) {
        ParamData pd = new ParamData();
        pd.put("q", StringUtils.replaceSqlPattern(q));
        pd.put("locked", locked);
        Org org = (Org) dao.findForObject("OrgMapper.findById", orgid);
        pd.put("orglongcode", org.getLongCode());
        pd.put("isIncludeSubOrg", isIncludeSubOrg);
        Pagination page = new Pagination();
        page.setCurrentPage(pageindex);
        page.setPageSize(pageSize);
        pd.setPagination(page);

        List<OrgUserDto> users = dao.findForList("UserOrgMapper.findByFilterListPage", pd, OrgUserDto.class);

        return new QResultDto(users, page);
    }

    @Override
    public ResultDto findByFilterNameOrIdListPage(int orgid, int locked, String q, boolean isIncludeSubOrg, int pageindex, int pageSize) {
        ParamData pd = new ParamData();
        pd.put("q", StringUtils.replaceSqlPattern(q));
        pd.put("locked", locked);
        Org org = (Org) dao.findForObject("OrgMapper.findById", orgid);
        pd.put("orglongcode", org.getLongCode());
        pd.put("isIncludeSubOrg", isIncludeSubOrg);
        Pagination page = new Pagination();
        page.setCurrentPage(pageindex);
        page.setPageSize(pageSize);
        pd.setPagination(page);

        List<OrgUserDto> users = dao.findForList("UserOrgMapper.findListPage", pd, OrgUserDto.class);

        return new QResultDto(users, page);
    }


    /**
     * 模糊匹配可用用户
     *
     * @param q
     */
    @Override
    public ResultDto findByFilter(String q) {
        ParamData pd = new ParamData();
        pd.put("q", StringUtils.replaceSqlPattern(q));
        List<SimpleUserDto> users = dao.findForList("UserDetailMapper.findByFilter", pd, SimpleUserDto.class);
        return new ResultDto(users);
    }

    @Override
    public ResultDto findByCodeLike(String q) {

        ParamData pd = new ParamData();
        pd.put("q", StringUtils.replaceSqlPattern(q));
        List<SimpleUserDto> users = dao.findForList("UserDetailMapper.findByCodeLike", pd, SimpleUserDto.class);
        return new ResultDto(users);
    }


    @Override
    public List<User> findByIds(List<Integer> ids) {
        ParamData pd = new ParamData();
        pd.put("list", ids);
        List<User> userList = dao.findForList("UserMapper.findByIds", pd, User.class);
        return userList;
    }

    /**
     * 模糊匹配可用用户-bd
     *
     * @param q
     */
    @Override
    public ResultDto findBdsByFilter(String q, int pageIndex, int pageSize) {
        q = StringUtils.replaceSqlPattern(q);
        QueryParams qp = new QueryParams(pageSize, pageIndex, q, "");
        ParamData pd = this.convertQueryParams(qp);
        List<SimpleUserDto> users = dao.findForList("UserDetailMapper.findBdsByFilterListPage", pd, SimpleUserDto.class);
        return new QResultDto(users, pd.getPagination());
    }


    /**
     * -
     *
     * @see UserService#updateUser(int,
     * UserDto)
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int updateUser(int userId, UserDto userDto) throws ParseException {
        checkDataValid(userDto);
        User user = (User) dao.findForObject("UserMapper.findById", userId);
        if (user == null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NOT_FOUND, userId);
        }

        user.setMobilephone(userDto.getMobilephone());
        user.setEmail(userDto.getEmail());
        user.setDescription(userDto.getDescription());
        user.setCode(userDto.getCode());
        user.setUserName(user.getCode());
        // 检查数据不能重复
        checkUserExist(user);
        dao.update("UserMapper.update", user);

        UserDetail ud = (UserDetail) dao.findForObject("UserDetailMapper.findByUserId", userId);
        ud.setSex(userDto.getSex());
        if (StringUtils.hasLength(userDto.getBirthday())) {
            ud.setBirthday(DateUtils.convertToDate(userDto.getBirthday(), DateUtils.FORMAT_SIMPLE));
        } else {
            ud.setBirthday(DateUtils.convertToDate("1970-01-01", DateUtils.FORMAT_SIMPLE));
        }
        ud.setFullName(userDto.getFullName());
        ud.setTelephone(userDto.getTelephone());
        ud.setAddress(userDto.getAddress());
        ud.setEmergencyContact(userDto.getEmergencyContact());
        ud.setEmergencyPhone(userDto.getEmergencyPhone());
        ud.setAvatarId(userDto.getAvatarId());
        ud.setPositionCode(userDto.getPositionCode());
        dao.update("UserDetailMapper.update", ud);

        // 修改用户组织表
        UserOrg uo = (UserOrg) dao.findForObject("UserOrgMapper.findGroup1RelByUserId", userId);
        uo.setOrgId(userDto.getOrgId());
        dao.update("UserOrgMapper.update", uo);

        //设置头像为非临时等信息
        SysFile sysFile = sysFileService.getFileInfo(userDto.getAvatarId());
        if (sysFile != null && sysFile.getIsTempFile()) {
            sysFileService.updateFileInfo(sysFile.getFileId(), "sys_user",
                    sysFile.getFileName(), sysFile.getContentType(), "用户" + user.getId() + "头像", false, 1);
        }
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        userDto.setId(userId);
        dataBackup.put("UPDATE_USER", userDto);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.UPDATE, "修改用户", dataBackup);
        return userId;
    }

    private void checkDataValid(UserDto userDto) {
        if (StringUtils.isEmpty(userDto.getPositionCode())) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_ARGUMENT_EMPTY, "positionCode");
        }
        if (userDto.getOrgId() == 0) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_ARGUMENT_EMPTY, "orgId");
        }

        if (userDto.getFullName() != null) {
            userDto.setFullName(userDto.getFullName().trim());
        }
        if (StringUtils.isEmpty(userDto.getFullName())) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_ARGUMENT_EMPTY, "fullName");
        }

        if (userDto.getCode() != null) {
            userDto.setCode(userDto.getCode().trim());
        }
        if (StringUtils.isEmpty(userDto.getCode())) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_ARGUMENT_EMPTY, "code");
        }

        if (userDto.getMobilephone() != null) {
            userDto.setMobilephone(userDto.getMobilephone().trim());
        }
        if (StringUtils.isEmpty(userDto.getMobilephone())) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_ARGUMENT_EMPTY, "mobilephone");
        }

        if (userDto.getEmail() != null) {
            userDto.setEmail(userDto.getEmail().trim());
        }

        if (StringUtils.isEmpty(userDto.getEmail())) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_ARGUMENT_EMPTY, "email");
        }

    }

    private void checkUserExist(User user) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        map.put("code", user.getCode());
        User userExist = (User) dao.findForObject("UserMapper.findByUserCode", map);
        if (userExist != null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_USER_CODE_EXIST);
        }
        map = new HashMap<>();
        map.put("id", user.getId());
        map.put("email", user.getEmail());
        userExist = (User) dao.findForObject("UserMapper.findByEmail", map);
        if (userExist != null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_USER_EMAIL_EXIST);
        }
        map = new HashMap<>();
        map.put("id", user.getId());
        map.put("userName", user.getUserName());
        userExist = (User) dao.findForObject("UserMapper.findByUserName", map);
        if (userExist != null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NAME_EXIST, user.getUserName());
        }
    }

    /**
     * -
     *
     * @see UserService#deleteUserById(java.lang.Integer)
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteUserById(Integer userId) {
        User user = (User) dao.findForObject("UserMapper.findById", userId);
        if (user == null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NOT_FOUND, userId);
        }
        if (user.getIsDeleted()) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_HAS_DELETED, userId);
        }
        dao.update("UserMapper.deleteUserById", userId);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_USER", userId);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.DELETE, "删除用户", dataBackup);
    }

    /**
     * 删除用户
     *
     * @see UserService#deleteUsersById(String[])
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteUsersById(String[] userId) {
        if (userId.length == 0) {
            return;
        }
        dao.update("UserMapper.deleteUserByUserIds", userId);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_USER", userId);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.DELETE, "删除用户", dataBackup);
    }

    /**
     * 校验工号
     *
     * @param code
     */
    @Override
    public void userCodeCheck(String code) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", null);
        map.put("code", code);
        User userExist = (User) dao.findForObject("UserMapper.findByUserCode", map);
        if (userExist != null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_USER_CODE_EXIST);
        }

    }

    /**
     * 校验邮件
     *
     * @param email
     */
    @Override
    public void userEmailCheck(int userId, String email) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", userId);
        map.put("email", email);
        User userExist = (User) dao.findForObject("UserMapper.findByEmail", map);
        if (userExist != null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_USER_EMAIL_EXIST);
        }
    }

    /**
     * 锁定用户
     *
     * @see UserService#lockUserByUserIds(java.util.List<Integer>)
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void lockUserByUserIds(List<Integer> userIds) {
        if (userIds == null || userIds.size() <= 0) {
            return;
        }
        dao.update("UserMapper.lockUserByUserIds", userIds);
        //剔出已经登录的用户
        List<User> users = dao.findForList("UserMapper.findByIds", userIds, User.class);
        if (users.size() > 0) {
            for (User user : users) {
                eventBus.post(user.getUserName());
            }
        }
        //添加要更新数据的日志信息
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_USER", userIds);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER,
                UserActions.LOCK, "锁定用户：(ids)" + String.valueOf(userIds), dataBackup);
    }

    /**
     * 解锁用户
     *
     * @see UserService#unLockUserByUserIds(java.util.List<Integer>)
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void unLockUserByUserIds(List<Integer> userIds) {
        if (userIds != null && userIds.size() > 0) {
            dao.update("UserMapper.unLockUserByUserIds", userIds);
        }
        //添加要更新数据的日志信息
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_USER", userIds);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.UNLOCK,
                "解锁用户：(ids)" + String.valueOf(userIds), dataBackup);
    }


    /**
     * -
     *
     * @see UserService#removeUserRole(int, int)
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void removeUserRole(int userId, int roleId) {
        User user = (User) dao.findForObject("UserMapper.findById", userId);
        if (user == null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NOT_FOUND, userId);
        }

        List<UserRole> urs = dao.findForList("UserRoleMapper.findByUserId", userId, UserRole.class);
        // 待移除角色id
        List<Integer> deleted = new ArrayList<>();
        for (UserRole ur : urs) {
            if (ur.getRoleId() == roleId) {
                deleted.add(ur.getId());
                break;
            }
        }
        if (deleted.size() == 0) {
            return;
        }
        dao.delete("UserRoleMapper.deleteById", deleted.get(0));
        //保存操作日志
        String log = String.format("删除用户" + userId + "%s%s", "的角色", roleId);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.DELETE,
                log, null);
    }

    /**
     * 根据userid获取用户信息
     *
     * @see UserService#getUserById(int)
     */
    @Override
    public UserDto getUserById(int userId) {
        User user = (User) dao.findForObject("UserMapper.findById", userId);
        if (user == null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NOT_FOUND, userId);
        }
        UserDto dto = new UserDto();
        if (user.getId() != null) {
            UserDetail ud = (UserDetail) dao.findForObject("UserDetailMapper.findByUserId", userId);
            BeanUtils.copyProperties(ud, dto);
            dto.setBirthday(DateUtils.formatDetailDate(ud.getBirthday()));
        }
        BeanUtils.copyProperties(user, dto);
        dto.setLastUpdateTime(DateUtils.formatDetailDate(user.getLastUpdateTime()));
        dto.setCreateTime(DateUtils.formatDetailDate(user.getCreateTime()));
        dto.setPassword("******");

        UserOrg userOrg = (UserOrg) dao.findForObject("UserOrgMapper.findGroup1RelByUserId", userId);
        if (userOrg != null) {
            Org org = (Org) dao.findForObject("OrgMapper.findById", userOrg.getOrgId());
            dto.setOrgName(org.getShortName());
            dto.setOrgId(userOrg.getOrgId());
        }

        SysFile sysFile = sysFileService.getFileInfo(dto.getAvatarId());
        if (sysFile != null) {
            dto.setAvatarPath(sysFile.getFileLocation());
        }
        return dto;
    }

    /**
     * 移动用户的组织
     *
     * @see UserService#moveUsersOrg(int, java.lang.String[])
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void moveUsersOrg(int targetOrgId, String[] userIds) {

        Org targetOrg = (Org) dao.findForObject("OrgMapper.findById", targetOrgId);
        if (targetOrg == null || targetOrg.getOrgGroupId() != 1) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NOT_FOUND, targetOrgId);
        }
        // 拆分用户
        if (userIds.length == 0) {
            return;
        }
        List<Integer> usersList = new ArrayList<>();
        for (String userId : userIds) {
            usersList.add(Integer.parseInt(userId));
        }
        // 查询userIds的组织机构id
        List<UserOrg> userOrgList = dao.findForList("UserOrgMapper.findGroup1RelByUserIds",
                usersList, UserOrg.class);

        if (userOrgList.size() > 0) {
            List<Integer> ids = EntityUtils.getIntPropListFromBeans(userOrgList, "id");
            Map<String, Object> map = new HashMap<>();
            map.put("list", ids);
            map.put("targetOrgId", targetOrgId);
            dao.update("UserOrgMapper.updateOrgIdById", map);
        }
        //保存操作日志
        //String log=String.format("将用户"+  ToStringBuilder.reflectionToString(userIds)+"%s%s%s","移动到组织",targetOrgId,"中");          
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_USER", userIds);
        String log = String.format("移动用户到组织" + "%s%s", targetOrgId, "中");
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.UPDATE, log, dataBackup);
    }

    /**
     * 修改用户密码
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void changePassword(int userId, UserChangePasswordDto userChangePasswordDto) {
        User user = (User) dao.findForObject("UserMapper.findById", userId);
        if (user == null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NOT_FOUND, userId);
        }
        String oldHash = new Md5Hash(userChangePasswordDto.getOldPassword(), user.getCredentialSalt()).toString()
                .toUpperCase();
        if (!oldHash.equals(user.getPassword())) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_USER_OLD_PASS_NOT_MATCH);
        }
        if (!CheckDataUtils.checkPassword(userChangePasswordDto.getNewPassword())) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_USER_PASSWORD_FORMAT_ERROR);
        }
        user.setPassword(
                new Md5Hash(userChangePasswordDto.getNewPassword(), user.getCredentialSalt()).toString().toUpperCase());
        if (user.getPassword().equals(oldHash)) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_USER_NEW_PASSWORD_MATCH_OLD_PASS);
        }
        dao.update("UserMapper.update", user);
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_USER", userChangePasswordDto);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.UPDATE, "修改用户密码", dataBackup);
    }

    /**
     * 重置用户的密码
     *
     * @see UserService#resetUsersPasswd(List
     * <Integer> )
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void resetUsersPasswd(List<Integer> userIds) {
        for (Integer userId : userIds) {
            User user = (User) dao.findForObject("UserMapper.findById", userId);
            if (user != null) {
                String randomPassword = CredentialUtils.randomPassword();
                user.setPassword(new Md5Hash(randomPassword, user.getCredentialSalt()).toString().toUpperCase());
                dao.update("UserMapper.update", user);
                // 发邮件
                Map<String, Object> emailBodyMap = new HashMap<>();
                emailBodyMap.put("username", user.getCode());
                emailBodyMap.put("password", randomPassword);
                String emailBody = JsonUtils.toJSONString(emailBodyMap);
                mailService.createMail("sys.logistics.master@hna.com", new String[]{user.getEmail()},
                        "运营平台账号密码重置通知",
                        emailBody, TemplateConstants.RESET_PASSOWRD);
            }
        }
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_USER", userIds);
        PrincipalLogUtils.addOperationLog(ModuleNames.SYS, ModuleNames.SYS_USER, UserActions.UPDATE, "重置用户密码", dataBackup);
    }

    /**
     * 给指定的角色全量分配成员，必须删除之前关系表中的关系
     *
     * @param roleId
     * @param members
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void assignRoleMembers(int roleId, List<RoleMembership> members) {

        // 先删除
        dao.delete("UserRoleMapper.deleteByRoleId", roleId);
        if (members == null || members.size() == 0) {
            return;
        }

        List<UserRole> addedUserRole = new ArrayList<>();

        for (RoleMembership member : members) {
            UserRole ur = new UserRole();
            ur.setUserId(member.getIdAsInteger());
            ur.setRoleId(roleId);
            addedUserRole.add(ur);
        }
        if (addedUserRole.size() == 0) {
            return;
        }
        dao.batchInsert("UserRoleMapper.insert", addedUserRole);
    }

    /**
     * 删除角色分配的成员
     *
     * @param roleId
     * @param members
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void removeRoleMembers(int roleId, List<RoleMembership> members) {
        if (members == null || members.size() == 0) {
            return;
        }

        List<Integer> memberIds = new ArrayList<>();
        members.forEach(member -> {
            if (member.getIdAsInteger() > 0) {
                memberIds.add(member.getIdAsInteger());
            } else {
                throw Exceptions.bizException(SysErrorCodes.ERROR_ARGUMENT_EMPTY, "null userId");
            }
        });

        Map<String, Object> param = new HashMap<>();
        param.put("roleId", roleId);
        param.put("list", memberIds);
        dao.delete("UserRoleMapper.deleteByRoleIdAndUserIds", param);
    }


    /**
     * 根据userId查找用户的组织机构(包括组织机构和用户组)
     *
     * @param userId
     */
    @Override
    public List<UserOrg> getOrgByUserId(int userId) {
        List<UserOrg> userOrgList = dao.findForList("UserOrgMapper.findByUserId", userId, UserOrg.class);
        return userOrgList;
    }

    @Override
    public String getMembershipTypeName() {
        return MEMBERSHIP_TYPE_NAME;
    }

    @Override
    public boolean isMembershipAcceptable(RoleMembership membership) {
        return membership != null && MembershipType.USER.equals(membership.getMembershipType());
    }

    @Override
    public List<Role> getRolesByMember(RoleMembership member) {
        List<Role> roleList = new ArrayList<>();
        if (!isMembershipAcceptable(member)) {
            return null;
        }


        int domainId = PrincipalUtils.getDomainId();
        ParamData pd = new ParamData();
        pd.put("userId", member.getIdAsInteger());
        pd.put("domainId", domainId);

        // 根据userId查询用户直接赋有的角色
        List<Role> rolesByUser = dao.findForList("UserRoleMapper.findRoleByUserId", pd, Role.class);

        // 合并用户所有不重复的角色
        getMergedRole(roleList, rolesByUser);

        // 根据userId查询用户所在机构的角色
        UserOrg userOrgs = (UserOrg) dao.findForObject("UserOrgMapper.findGroup1RelByUserId", member.getIdAsInteger());
        if (userOrgs != null) {
            RoleMembership memberOrg = new RoleMembership(userOrgs.getOrgId(), MembershipType.ORGANIZATION);
            List<Role> rolesByOrg = orgService.getRolesByMember(memberOrg);
            getMergedRole(roleList, rolesByOrg);
            // 根据userId所在的用户分组的角色
            List<UserOrg> userGroups = dao.findForList("UserOrgMapper.findGroup2RelByUserId",
                    member.getIdAsInteger(), UserOrg.class);
            if (!CollectionUtils.isEmpty(userGroups)) {
                for (UserOrg uo : userGroups) {
                    RoleMembership memberUserGroup = new RoleMembership(uo.getOrgId(), MembershipType.USER_GROUP);
                    List<Role> rolesByUserGroup = orgService.getRolesByMember(memberUserGroup);
                    getMergedRole(roleList, rolesByUserGroup);
                }
            }
        }

        return roleList;
    }

    /**
     * 获取总的角色列表，遍历组织机构角色列表，如果用户角色列表中没有则将此角色添加到用户角色列表中
     *
     * @param roles
     * @param rolesWillAccept
     * @return
     */
    private void getMergedRole(List<Role> roles, List<Role> rolesWillAccept) {
        if (CollectionUtils.isEmpty(rolesWillAccept)) {
            return;
        }
        // 遍历本组织机构的所有角色
        for (Role orgRole : rolesWillAccept) {
            // 标志位：0表示不存在，1表示存在
            int flag = 0;
            // 在总的角色List遍历，查询当前角色是不是已经加入角色列表中
            for (Role role : roles) {
                // 相等说明已经存在
                if (orgRole.getId().equals(role.getId())) {
                    flag = 1;
                }
            }
            // 当前角色不在总的角色列表中，则添加此角色到角色列表中
            if (flag == 0) {
                roles.add(orgRole);
            }
        }
    }

    /**
     * 通过组织code 来查询用户
     *
     * @param orgCode
     * @return
     */
    @Override
    public List<OrgUserDto> findUserByOrgCode(String orgCode) {
        return dao.findForList("UserOrgMapper.findByCode", orgCode, OrgUserDto.class);
    }

    /**
     * 查询用户的明细
     *
     * @param userId
     */
    @Override
    public UserDto findUserDetailByUserId(int userId) {
        User user = (User) dao.findForObject("UserMapper.findById", userId);
        if (user == null) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_MODEL_NOT_FOUND, userId);
        }
        UserDto dto = new UserDto();
        if (user.getId() != null) {
            UserDetail ud = (UserDetail) dao.findForObject("UserDetailMapper.findByUserId", userId);
            BeanUtils.copyProperties(ud, dto);
            dto.setBirthday(DateUtils.formatDetailDate(ud.getBirthday()));
        }
        BeanUtils.copyProperties(user, dto);
        dto.setLastUpdateTime(DateUtils.formatDetailDate(user.getLastUpdateTime()));
        dto.setCreateTime(DateUtils.formatDetailDate(user.getCreateTime()));
        dto.setPassword("******");
        return dto;
    }

    /**
     * 查询用户的基本信息
     *
     * @param userId
     */
    @Override
    public UserDetail getSimpleUserById(int userId) {
        return (UserDetail) dao.findForObject("UserDetailMapper.getSimpleUserById", userId);
    }

    @Override
    public QResultDto findByFilterOrgCodeListPage(String orgCode, String q, int page, int pageSize) {
        q = StringUtils.replaceSqlPattern(q);
        QueryParams qp = new QueryParams(pageSize, page, q, "");
        ParamData pd = this.convertQueryParams(qp);
        pd.put("code", orgCode);
        List<OrgUserDto> results = dao.findForList("UserOrgMapper.findByCodeListPage", pd, OrgUserDto.class);
        QResultDto qResultDto = new QResultDto();
        qResultDto.setData(results);
        qResultDto.setPagination(pd.getPagination());
        return qResultDto;
    }


    @Override
    public List<UserOrg> findByOrgCode(String orgCode) {
        ParamData pd = new ParamData();
        pd.put("code", orgCode);
        List<UserOrg> results = dao.findForList("UserOrgMapper.findByOrgCode", pd, UserOrg.class);
        return results;
    }

    @Override
    public int findRandomUserIdByOrgCode(String orgCode) {
        int userId = 0;
        if (!StringUtils.isEmpty(orgCode)) {
            List<UserOrg> userOrgList = this.findByOrgCode(orgCode);
            if (!CollectionUtils.isEmpty(userOrgList)) {
                int index = (int) (Math.random() * userOrgList.size());
                UserOrg userOrg = userOrgList.get(index);
                userId = userOrg.getUserId();
            }
        }
        return userId;

    }

    @Override
    public ResultDto findShortListPage(String q, int pageIndex, int pageSize) {
        q = StringUtils.replaceSqlPattern(q);
        QueryParams qp = new QueryParams(pageSize, pageIndex, q, "");
        ParamData pd = this.convertQueryParams(qp);
        List<SimpleUserDto> users = dao.findForList("UserDetailMapper.findShortListPage", pd, SimpleUserDto.class);
        QResultDto qResultDto = new QResultDto();
        qResultDto.setData(users);
        qResultDto.setPagination(pd.getPagination());
        return qResultDto;
    }
}
